package cluster

import (
	"encoding/json"
	"lnzw/engine/log"
	"time"

	cpu "github.com/shirou/gopsutil/v3/cpu"
	"github.com/shirou/gopsutil/v3/disk"
	"github.com/shirou/gopsutil/v3/mem"
	"github.com/shirou/gopsutil/v3/net"
	"go.uber.org/zap"
)

var nodeType2Node = map[int32]INode{}

type INode interface {
	NodeId() int32
	NodeType() int32
	GetData() any
	Marshal() ([]byte, error)
	UnMarshal() error
	Update()
}

type DefaultNode struct {
	Id      int32
	Data    INodeData `json:"-"`
	DataRaw json.RawMessage
}

type INodeData interface {
	GetCPUPercent() float64
	GetMemPercent() float64
	GetDiskPercent() float64
	GetBytesSent() int64
	GetBytesRecv() int64
}

type DefaultNodeData struct {
	CpuPercent  float64 //cpu使用率
	MemPercent  float64 //内存使用率
	DiskPercent float64 //磁盘使用率
	ByteSent    int64   //发送字节数
	ByteRecv    int64   //接收字节数
}

func RegisterNodeTypeNode(node INode) {
	nodeType2Node[node.NodeType()] = node
}

func (n *DefaultNode) NodeId() int32 {
	return n.Id
}

func (n *DefaultNode) NodeType() int32 {
	panic("implement me")
}

func (n *DefaultNode) GetData() any {
	return n.Data
}

func (n *DefaultNode) SendMsg(bs []byte) {
}

func (n *DefaultNode) Marshal() ([]byte, error) {
	data, err := json.Marshal(n.Data)
	if err != nil {
		return nil, err
	}
	n.DataRaw = data
	rsData, err := json.Marshal(n)
	if err != nil {
		return nil, err
	}
	return rsData, nil
}

func (n *DefaultNode) Update() {
	//cpu使用率
	arr, err := cpu.Percent(time.Second, false)
	if err != nil {
		log.Logger.Error("get cpu info failed", zap.Error(err))
		return
	}
	n.Data.(*DefaultNodeData).CpuPercent = arr[0]
	//内存使用率
	m, err := mem.VirtualMemory()
	if err != nil {
		log.Logger.Error("get mem info failed", zap.Error(err))
		return
	}
	n.Data.(*DefaultNodeData).MemPercent = m.UsedPercent
	//磁盘使用率
	d, err := disk.Usage("/")
	if err != nil {
		log.Logger.Error("get mem info failed", zap.Error(err))
		return
	}
	n.Data.(*DefaultNodeData).DiskPercent = d.UsedPercent
	//网络流量
	ne, err := net.IOCounters(true)
	if err != nil {
		log.Logger.Error("get mem info failed", zap.Error(err))
		return
	}
	n.Data.(*DefaultNodeData).ByteSent = int64(ne[0].BytesSent)
	n.Data.(*DefaultNodeData).ByteRecv = int64(ne[0].BytesRecv)
}

func (n *DefaultNode) UnMarshal() error {
	panic("implement me")
}

func (n *DefaultNodeData) GetCPUPercent() float64 {
	return n.CpuPercent
}

func (n *DefaultNodeData) GetMemPercent() float64 {
	return n.MemPercent
}

func (n *DefaultNodeData) GetDiskPercent() float64 {
	return n.CpuPercent
}

func (n *DefaultNodeData) GetBytesSent() int64 {
	return n.ByteSent
}
func (n *DefaultNodeData) GetBytesRecv() int64 {
	return n.ByteRecv
}
